package com.soup.hummingbird.module.method.config;

import lombok.extern.slf4j.Slf4j;

import java.util.HashSet;
import java.util.Set;

/**
 * 〈收集信息插桩配置类，配置无需插桩的包和方法名，并提供相关的判断方法〉<br>
 *
 * @author zhaoyi
 * @date 2021-04-04 17:00
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Slf4j
public class ProfilingFilter {
    private static Set<String> exceptPackagePrefix = new HashSet<>();

    private static Set<String> exceptMethods = new HashSet<>();

    static {

        /*InputStream is = FilterConf.class.getResourceAsStream("profiling-filter.yml");
        Yaml filter = new Yaml();
        FilterConf conf  = filter.loadAs(is, FilterConf.class);
        System.out.println(conf.getExceptMethods());
        System.out.println(conf.getExceptPackagePrefix());*/

        // 默认不注入的包
        exceptPackagePrefix.add("java/");
        exceptPackagePrefix.add("javax/");
        exceptPackagePrefix.add("sun/");
        exceptPackagePrefix.add("com/sun/");
        exceptPackagePrefix.add("com/intellij/");
        exceptPackagePrefix.add("org/jetbrains/");
        exceptPackagePrefix.add("org/slf4j");
        exceptPackagePrefix.add("com/alibaba");
        exceptPackagePrefix.add("ch/qos/logback");
        exceptPackagePrefix.add("cn/hutool/");
        // 不注入监控工程
        exceptPackagePrefix.add("com/soup/hummingbird");

        // 默认不注入的方法
        exceptMethods.add("main");
        exceptMethods.add("premain");
        exceptMethods.add("getClass");//java.lang.Object
        exceptMethods.add("hashCode");//java.lang.Object
        exceptMethods.add("equals");//java.lang.Object
        exceptMethods.add("clone");//java.lang.Object
        exceptMethods.add("toString");//java.lang.Object
        exceptMethods.add("notify");//java.lang.Object
        exceptMethods.add("notifyAll");//java.lang.Object
        exceptMethods.add("wait");//java.lang.Object
        exceptMethods.add("finalize");//java.lang.Object
        exceptMethods.add("afterPropertiesSet");//spring
    }

    /**
     * 类是否需要进行插桩
     * @param className 全限定类名
     * @return true 需要注入 | false 不需要
     */
    public static boolean isNotNeedInject(String className) {
        if (null == className) {
            return false;
        }

        for (String prefix : exceptPackagePrefix) {
            if (className.startsWith(prefix)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断方法名是否需要进行插桩
     * @param methodName 方法名称
     * @return true 需要 | false 不需要
     */
    public static boolean isNotNeedInjectMethod(String methodName) {
        if (null == methodName) {
            return false;
        }

        return exceptMethods.contains(methodName);
    }

}
